using System;
using System.Web;
using System.Web.UI;
using System.ComponentModel;

namespace Deepcode.Flux.Core.UI.Controls
{
	/// <summary>
	/// TabBlock implements a tab view control, which works entirely client side 
	/// using hidden / revealed DIV's as the pages. The TabBlock remembers the 
	/// tab selection during postback though.
	/// </summary>
	[
	DefaultProperty( "Tabs" ),
	ParseChildren(true, "Tabs")
	]
	public class TabBlock : Deepcode.Flux.Core.UI.Controls.Base.BaseControl
	{
		/// <summary>
		/// The protected collection object to hold the tabs
		/// </summary>
		protected TabCollection _tabs;
		#region Properties
		/// <summary>
		/// The Tabs collection which holds all of the tabs on this control
		/// </summary>
		[
		PersistenceMode(PersistenceMode.InnerDefaultProperty)
		]
		public TabCollection Tabs
		{
			get
			{
				if( _tabs == null )
				{
					_tabs = new TabCollection();
					if( IsTrackingViewState ) ((IStateManager) _tabs).TrackViewState();
				}
				return _tabs;
			}
		}
		#endregion
		/// <summary>
		/// Gets appropriate script to set the specified tab active
		/// </summary>
		/// <param name="t"></param>
		/// <returns></returns>
		private string SetTabActiveScript( Tab t )
		{
			string script = String.Format( "__Flux_SetActiveTab('{0}', '{1}', '{2}');",
				t.ContainerID + "tab",
				this.ClientID + "hidden",
				t.ContainerID);

			return script;
		}
		
		#region Rendering
		/// <summary>
		/// Renders the HTML for the tab block
		/// </summary>
		/// <param name="writer"></param>
		protected override void Render(HtmlTextWriter writer)
		{
			writer.Write("<table width='100%' cellspacing=0 cellpadding=0 border=0>");
			writer.Write("<tr><td class='StyleTabBlockCell'>");

			foreach( Tab tab in Tabs )
			{
				// Create the onclick script
				string clickScript = SetTabActiveScript( tab );
				// Render the tab
				writer.Write("<div style=\"float:left;\">");
				writer.Write("<table class='StyleTabTable' cellspacing=0 cellpadding=0 border=0><tr>");
				writer.Write("<td onclick=\"{0}\" nowrap='true' class='StyleTabInactive' id='{1}tab'>", clickScript, tab.ContainerID);
				writer.Write("&nbsp;&middot; {0} &nbsp;&nbsp;", tab.Title);
				writer.Write("</td>");
				writer.Write("</tr></table>");
				writer.Write("</div>");
			}
			writer.Write("</td></tr></table>");
		}
		#endregion
		#region Init / Setup
		/// <summary>
		/// Includes the stylesheets needed to render a panel
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);
			// Include the stylesheet
			this.LoadClientStyleSheet("TabBlock/TabBlock.css", "Deepcode.Flux.Core.UI.Controls.TabBlockCSS");
			// Include the script
			this.LoadClientScript("TabBlock/TabBlock.js", "Deepcode.Flux.Core.UI.Controls.TabBlockJS");

			// Create a hidden field to store which tab is active
			string hFieldName = this.ClientID + "hidden";
			// Default to first visible tab if we don't know
			string setOn = "";
			if( Page.Request[hFieldName] != null )
				setOn = Page.Request[hFieldName];

			// Register the hidden field to store which tab is active
			Page.ClientScript.RegisterHiddenField( hFieldName, setOn );
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad (e);
			string hFieldName = this.ClientID + "hidden";
			string setOn = "";
			if( Page.Request[hFieldName] == null )
			{
				ActivateFirstTab();
			}
			else
			{
				// Has this been posted back - if so, hidden field tells us which tab is active
				setOn = Page.Request[hFieldName];
			}
			// Only default if we have something to default to
			if( setOn != "" )
			{
				// Get the tab
				foreach( Tab t in this.Tabs )
					if( t.ContainerID == setOn )
					{
						Page.ClientScript.RegisterStartupScript(
							this.GetType(),
							"Deepcode.Flux.UI.Controls.TabBlockJSStartup",
							String.Format("<script language=\"javascript\">{0}</script>", this.SetTabActiveScript( t )));

						break;
					}
			}

		}

		/// <summary>
		/// When populating the tabs dynamically, call ActivateFirstTab to ensure the first
		/// available tab is activated.
		/// </summary>
		public void ActivateFirstTab()
		{
			if( Tabs.Count > 0 )
			{
				Page.ClientScript.RegisterStartupScript(
					this.GetType(),
					"Deepcode.Flux.UI.Controls.TabBlockJSStartup",
					String.Format("<script language=\"javascript\">{0}</script>", this.SetTabActiveScript( Tabs[0] )));
			}
		}
		#endregion
		#region Custom Viewstate management
		protected override void LoadViewState( object savedState )
		{
			// Load view state must load any of my viewstate properties and then
			// also load any child tab properties too...
			object myState = null;
			object tabState = null;
			object[] saveState = null;
			
			if( savedState != null )
			{
				saveState = (object[]) savedState;
				if( saveState.Length != 2 ) throw new ArgumentException("Invalid viewstate!");

				myState = saveState[0];
				tabState = saveState[1];
			}

			base.LoadViewState( myState );
			if( (tabState != null)) ((IStateManager)Tabs).LoadViewState(tabState);
		}
		protected override object SaveViewState()
		{
			// Save view state must first of all save any of my viewstate properties
			// and then save the child tab properties too...
			object myState = base.SaveViewState();
			object tabState = null;

			if((_tabs != null) && (_tabs.Count > 0)) 
			{
				tabState = ((IStateManager)_tabs).SaveViewState();
			}

			if( (myState != null ) || (tabState != null ))
			{
				object [] saveState = new object[2];
				saveState[0] = myState;
				saveState[1] = tabState;
				return saveState;
			}
			return null;
		}
		protected override void TrackViewState()
		{
			base.TrackViewState();
			if( _tabs != null ) ((IStateManager) _tabs).TrackViewState();
		}
		#endregion
	}
}
